/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package dao;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;
import model.Pessoa;

/**
 *
 * @author KDC
 */
public class PessoaDAOXML extends IPessoaDAO<Pessoa> {

    private TreeSet<Pessoa> pessoas = null;
    private final File arquivo;
    private static PessoaDAOXML instance;

    public PessoaDAOXML() throws FileNotFoundException {
        if (pessoas == null) {
            pessoas = new TreeSet<Pessoa>();
        }
        arquivo = new File("src/data/Contato.xml");
        carregaPessoas();
    }

    public static PessoaDAOXML getInstance() throws FileNotFoundException {
        if (instance == null) {
            instance = new PessoaDAOXML();
        }
        return instance;
    }

    @Override
    public void carregaPessoas() throws FileNotFoundException {
        FileReader reader = null;
        try {
            //carrega o arquivo XML para um objeto reader
            reader = new FileReader(arquivo);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //Cria o objeto xstream
        XStream xStream = new XStream(new DomDriver());
        //informamos as tags que serão lidas, da mesma forma como foi feita no GravandoXML
        xStream.alias("contatos", TreeSet.class);
        xStream.alias("contato", Pessoa.class);
        //cria uma lista de contatos, contendo todos os dados do xml
        //List contatos = (List) xStream.fromXML(reader);
        pessoas = (TreeSet<Pessoa>) xStream.fromXML(reader);

        //return contatos;
    }

    @Override
    public boolean add(Pessoa p) throws IOException {
        boolean add = false;
        pessoas.add(p);
        //reader = new FileReader(arquivo);

        add = this.pessoas.add(p);
        XStream xStream = new XStream(new DomDriver("ISO-8859-1"));

        xStream.alias("contatos", List.class);
        xStream.alias("contato", Pessoa.class);

        File arquivo = new File("Contato.xml");
        FileOutputStream gravar;
        try {
            gravar = new FileOutputStream(arquivo);
            gravar.write(xStream.toXML(arquivo).getBytes());
            gravar.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        notifyObservers();
        return add;
    }

    @Override
    public boolean remove(String nome) throws IOException {
        TreeSet<Pessoa> listaTemp = new TreeSet<Pessoa>();
        for (Iterator<Pessoa> it = pessoas.iterator(); it.hasNext();) {
            Pessoa pessoa = it.next();
            if (!pessoa.getNome().equals(nome)) {
                listaTemp.add(pessoa);
            }
        }
        boolean remove = limpaArquivo(arquivo);
        if (remove) {
            addAll(listaTemp);
        }
        return remove;
    }

    @Override
    public boolean altera(Pessoa pessoaExistente, String nomeAnterior) throws IOException {
        TreeSet<Pessoa> listaTemp = new TreeSet<Pessoa>();
        for (Iterator<Pessoa> it = pessoas.iterator(); it.hasNext();) {
            Pessoa pessoa = it.next();
            if (!pessoa.getNome().equals(nomeAnterior)) {
                listaTemp.add(pessoa);
            } else {
                listaTemp.add(pessoaExistente);
            }
        }
        boolean remove = limpaArquivo(arquivo);
        if (remove) {
            addAll(listaTemp);
        }
        return remove;
    }

    @Override
    public void addAll(Collection<Pessoa> pessoas) throws IOException {
        FileWriter w = new FileWriter(arquivo, true);
        BufferedWriter bf = new BufferedWriter(w);
        for (Iterator<Pessoa> it = pessoas.iterator(); it.hasNext();) {
            Pessoa pessoa = it.next();
            bf.write(pessoa.toString());
            bf.newLine();
        }
        bf.close();
        carregaPessoas();
        notifyObservers();
    }

    private boolean limpaArquivo(File arquivo) throws FileNotFoundException {
        PrintWriter writer = new PrintWriter(arquivo);
        writer.print("");
        writer.flush();
        writer.close();
        return !writer.checkError();
    }

    @Override
    public Pessoa getPessoaByName(String nome) {
        for (Iterator<Pessoa> it = pessoas.iterator(); it.hasNext();) {
            Pessoa pessoa = it.next();
            if (pessoa.getNome().equals(nome)) {
                return pessoa;
            }
        }
        return null;
    }

    @Override
    public boolean contains(Pessoa p) {

        return this.pessoas.contains(p);
    }

    @Override
    public Collection<Pessoa> getPessoas() {
        return pessoas;
    }

}
